package com.solution.admin.promotion.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.solution.admin.product.constants.ProductConstants.GiftType;
import com.solution.admin.product.constants.ProductConstants.ProductType;
import com.solution.admin.promotion.constants.PromotionConstants;
import com.solution.admin.promotion.dao.PromotionDao;
import com.solution.admin.promotion.dao.PromotionProductDao;
import com.solution.admin.promotion.dao.PromotionRuleDiscountDao;
import com.solution.admin.promotion.dao.PromotionRuleGiftDao;
import com.solution.admin.promotion.dao.PromotionRuleReduceDao;
import com.solution.admin.promotion.dao.PromotionTargetDao;
import com.solution.admin.promotion.entity.PromotionEntity;
import com.solution.admin.promotion.entity.PromotionProductEntity;
import com.solution.admin.promotion.entity.PromotionRuleDiscountEntity;
import com.solution.admin.promotion.entity.PromotionRuleGiftEntity;
import com.solution.admin.promotion.entity.PromotionRuleReduceEntity;
import com.solution.admin.promotion.entity.PromotionRulesEntity;
import com.solution.admin.promotion.entity.PromotionTargetEntity;
import com.solution.admin.promotion.service.PromotionService;
import com.solution.common.constants.PublicStatus.SysSymbol;
import com.solution.common.dao.BaseDao;
import com.solution.common.page.PageBean;
import com.solution.common.page.PageParam;
import com.solution.common.service.impl.BaseServiceImpl;
import com.solution.common.utils.string.StringUtil;

/**
 * 活动信息service实现层
 * 
 * @author xu_cc
 * @date 2017-09-27 23:24:51
 */
@Service
public class PromotionServiceImpl extends BaseServiceImpl<PromotionEntity> implements PromotionService {

    /**
     * 活动信息接口
     */
    @Autowired
    PromotionDao promotionDao;

    @Autowired
    PromotionRuleReduceDao ruleReduceDao;

    @Autowired
    PromotionRuleGiftDao ruleGiftDao;

    @Autowired
    PromotionRuleDiscountDao ruleDiscountDao;

    @Autowired
    PromotionProductDao promotionProductDao;

    @Autowired
    PromotionTargetDao promotionTargetDao;

    protected BaseDao<PromotionEntity> getDao() {
        return this.promotionDao;
    }

    /**
     * 更新活动状态（停用、启用）
     * 
     * @param PromotionEntity
     *            活动信息对象
     * @return int 更新是否成功，>1代表更新成功
     * @author xu_cc
     * @date 2017-09-27 23:24:51
     */
    @Caching(evict = { 
            @CacheEvict(value = "promotion", key = "'PROMOTION_' + #promotionEntity.id"),
            @CacheEvict(value = "promotion", key = "'PROMOTION_RULE_' + #promotionEntity.id")})
    public int updatePromotionStatus(PromotionEntity promotionEntity) throws Exception {
        return promotionDao.updatePromotion(promotionEntity);
    }

    /**
     * 更新活动信息(包括活动商品、对象、规则)
     * 
     * @param promotionEntity
     *            活动信息实体
     * @return Long 更新是否成功，>1代表更新成功
     * @author xu_cc
     * @date 2017-09-27 23:24:51
     */
    @Override
    @Caching(evict = { 
            @CacheEvict(value = "promotion", key = "'PROMOTION_' + #promotionEntity.id"),
            @CacheEvict(value = "promotion", key = "'PROMOTION_RULE_' + #promotionEntity.id")})
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public int updatePromotion(PromotionEntity promotionEntity) throws Exception {
        // 首先执行插入获取主信息
        Long promotionId = promotionEntity.getId();
        promotionDao.updatePromotion(promotionEntity);
        // 删除满减规则
        ruleReduceDao.deleteById(promotionId);
        // 删除满赠规则
        ruleGiftDao.deleteById(promotionId);
        // 删除折扣规则
        ruleDiscountDao.deleteById(promotionId);
        // 删除商品（条件商品、满赠商品）
        promotionProductDao.deleteById(promotionId);
        // 删除对象
        promotionTargetDao.deleteById(promotionId);
        // 通用活动保存方法
        doCommonSave(promotionId, promotionEntity);
        return 1;
    }

    /**
     * 活动新增、修改统一保存方法
     * 
     * @param promotionId
     * @param promotionEntity
     * @throws Exception
     *             void
     * @author xu_cc
     * @throws Exception
     *             exception
     * @Date 创建时间：2017年10月11日 上午11:52:23
     */
    @Caching(evict = { 
            @CacheEvict(value = "promotion", key = "'PROMOTION_' + #promotionId"),
            @CacheEvict(value = "promotion", key = "'PROMOTION_RULE_' + #promotionId")})
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void doCommonSave(Long promotionId, PromotionEntity promotionEntity) throws Exception {
        // 获取活动类型
        int promotionType = promotionEntity.getPromotionType();
        if (1 == promotionType) {
            // 满减
            // 插入满减规则
            List<PromotionRuleReduceEntity> ruleReduceList = doGetRuleReduce(promotionId, promotionEntity.getRuleJsonArr(),
                    promotionEntity.getIsLimit());
            for (PromotionRuleReduceEntity ruleReduce : ruleReduceList) {
                ruleReduceDao.savePromotionRuleReduce(ruleReduce);
            }
        } else if (2 == promotionType) {
            // 满赠
            // 插入满赠规则
            List<PromotionRuleGiftEntity> ruleGiftList = doGetRuleGift(promotionId, promotionEntity.getRuleJsonArr());
            for (PromotionRuleGiftEntity ruleGift : ruleGiftList) {
                // 根据
                long ruleGiftId = ruleGiftDao.savePromotionRuleGift(ruleGift);
                if (GiftType.GIFT_PRODUCT.equals(ruleGift.getGiftType())) {
                    // 赠品，需要将满赠商品再次保存一次
                    String[] proArr = ruleGift.getGiftProductCodeStr().split(SysSymbol.COMMA);
                    if (null != proArr && proArr.length > 0) {
                        for (String productCode : proArr) {
                            if (StringUtil.isEmpty(productCode)) {
                                continue;
                            }
                            // 满赠商品插入
                            PromotionProductEntity promotionProduct = new PromotionProductEntity();
                            promotionProduct.setProductCode(productCode);
                            promotionProduct.setPromotionId(promotionId);
                            // 商品类型
                            promotionProduct.setProductType(ProductType.PRODUCT_GIFT);
                            // 满赠商品对应规则
                            promotionProduct.setPromotionRuleId(ruleGiftId);
                            promotionProductDao.savePromotionProduct(promotionProduct);
                        }
                    } else {
                        throw new Exception("满赠商品设置失败！");
                    }
                }
            }
        } else if (3 == promotionType) {
            // 折扣
            // 插入折扣规则
            List<PromotionRuleDiscountEntity> ruleDiscountList = doGetRuleDiscount(promotionId, promotionEntity.getRuleJsonArr());
            for (PromotionRuleDiscountEntity ruleDiscount : ruleDiscountList) {
                ruleDiscountDao.savePromotionRuleDiscount(ruleDiscount);
            }
        } else {
            throw new Exception("未知的活动类型！");
        }
        // 插入活动商品
        String[] proIdArr = promotionEntity.getProductStr().split(SysSymbol.COMMA);
        if (null != proIdArr && proIdArr.length > 0) {
            for (String productCode : proIdArr) {
                if (StringUtil.isEmpty(productCode)) {
                    continue;
                }
                // 活动商品插入
                PromotionProductEntity promotionProduct = new PromotionProductEntity();
                promotionProduct.setProductCode(productCode);
                promotionProduct.setPromotionId(promotionId);
                promotionProduct.setProductType(ProductType.PRODUCT_NORMAL);
                promotionProductDao.savePromotionProduct(promotionProduct);
            }
        } else {
            throw new Exception("解析活动商品异常！");
        }
        // 插入活动对象
        String[] targetArr = promotionEntity.getTargetStr().split(SysSymbol.COMMA);
        if (null != targetArr && targetArr.length > 0) {
            for (String target : targetArr) {
                if (StringUtil.isEmpty(target) || target.indexOf(SysSymbol.NUMBER_SIGN) == -1) {
                    continue;
                }
                PromotionTargetEntity proTarget = new PromotionTargetEntity();
                proTarget.setPromotionId(promotionId);
                String[] properties = target.split(SysSymbol.NUMBER_SIGN);
                Long customerCustomId = Long.parseLong(properties[0]);
                proTarget.setCustomerCustomId(customerCustomId);
                proTarget.setPropertyValue(properties[1]);
                proTarget.setPropertyName(properties[2]);
                promotionTargetDao.savePromotionTarget(proTarget);
            }
        } else {
            throw new Exception("解析活动对象异常！");
        }
    }

    /**
     * 保存活动信息
     * 
     * @param promotionEntity
     *            活动信息实体
     * @return Long 添加成功活动信息的ID
     * @author xu_cc
     * @date 2017-09-27 23:24:51
     */
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public int savePromotion(PromotionEntity promotionEntity) throws Exception {
        // 首先执行插入获取主信息
        Long promotionId = promotionDao.savePromotion(promotionEntity);
        // 校验并组装数据
        doCommonSave(promotionId, promotionEntity);
        return 1;
    }

    /**
     * 解析满赠规则<br>
     * [{"orderMoney":"10","giftType":"1","giftValue":0,"couponId":"","giftProductCodeStr":
     * "123,456,"},<br>
     * {"orderMoney":"20","giftType":"2","giftValue":"2""couponId":"","giftProductCodeStr":""
     * },<br>
     * {"orderMoney":"30","giftType":"3","giftValue":"3""couponId":"","giftProductCodeStr":""
     * },<br>
     * {"orderMoney":"40","giftType":"1","giftValue":0,"couponId":"","giftProductCodeStr":
     * "999,333,"}]<br>
     * 
     * @param promotionId
     * @param ruleJsonArr
     * @return List<PromotionRuleGiftEntity>
     * @author xu_cc
     * @throws Exception
     *             exception
     * @Date 创建时间：2017年10月10日 下午7:45:23
     */
    private List<PromotionRuleGiftEntity> doGetRuleGift(Long promotionId, String ruleJsonArr) {
        List<PromotionRuleGiftEntity> ruleGiftList = new ArrayList<PromotionRuleGiftEntity>();
        JSONArray array = JSONArray.parseArray(ruleJsonArr);
        PromotionRuleGiftEntity ruleGift = null;
        JSONObject jsonObj = null;
        for (int j = 0; j < array.size(); j++) {
            jsonObj = array.getJSONObject(j);
            ruleGift = new PromotionRuleGiftEntity();
            ruleGift.setPromotionId(promotionId);
            ruleGift.setGiftType(jsonObj.getString("giftType"));
            ruleGift.setCouponId(jsonObj.containsKey("couponId") ? jsonObj.getLong("couponId") : null);
            ruleGift.setGiftProductCodeStr(jsonObj.getString("giftProductCodeStr"));
            ruleGift.setOrderMoney(getBigDecimalFromJson(jsonObj, "orderMoney"));
            ruleGift.setGiftValue(jsonObj.containsKey("giftValue") ? getBigDecimalFromJson(jsonObj, "giftValue") : null);
            ruleGiftList.add(ruleGift);
        }
        return ruleGiftList;

    }

    /**
     * 解析折扣规则
     * 
     * @param promotionId
     * @param ruleJsonArr
     * @return List<PromotionRuleDiscountEntity>
     * @author xu_cc
     * @throws Exception
     *             exception
     * @Date 创建时间：2017年10月9日 下午8:05:31
     */
    private List<PromotionRuleDiscountEntity> doGetRuleDiscount(Long promotionId, String ruleJsonArr) {
        List<PromotionRuleDiscountEntity> ruleDiscountList = new ArrayList<PromotionRuleDiscountEntity>();
        JSONArray array = JSONArray.parseArray(ruleJsonArr);
        PromotionRuleDiscountEntity ruleDiscount = null;
        JSONObject jsonObj = null;
        for (int j = 0; j < array.size(); j++) {
            jsonObj = array.getJSONObject(j);
            ruleDiscount = new PromotionRuleDiscountEntity();
            ruleDiscount.setPromotionId(promotionId);
            ruleDiscount.setOrderMoney(getBigDecimalFromJson(jsonObj, "orderMoney"));
            ruleDiscount.setDiscount(getBigDecimalFromJson(jsonObj, "discount"));
            ruleDiscountList.add(ruleDiscount);
        }
        return ruleDiscountList;
    }

    /**
     * 解析满减规则
     * 
     * @param promotionId
     * @param ruleJsonArr
     * @param isLimit
     * @return List<PromotionRuleReduceEntity>
     * @author xu_cc
     * @throws Exception
     *             exception
     * @Date 创建时间：2017年10月9日 下午4:31:12
     */
    private List<PromotionRuleReduceEntity> doGetRuleReduce(Long promotionId, String ruleJsonArr, String isLimit) {
        List<PromotionRuleReduceEntity> ruleReduceList = new ArrayList<PromotionRuleReduceEntity>();
        JSONArray array = JSONArray.parseArray(ruleJsonArr);
        PromotionRuleReduceEntity ruleReduce = null;
        JSONObject jsonObj = null;
        for (int j = 0; j < array.size(); j++) {
            ruleReduce = new PromotionRuleReduceEntity();
            jsonObj = array.getJSONObject(j);
            ruleReduce.setPromotionId(promotionId);
            ruleReduce.setOrderMoney(getBigDecimalFromJson(jsonObj, "orderMoney"));
            ruleReduce.setReduceMoney(getBigDecimalFromJson(jsonObj, "reduceMoney"));
            ruleReduce.setIsLimit(Integer.parseInt(isLimit));
            ruleReduceList.add(ruleReduce);
        }
        return ruleReduceList;
    }

    /**
     * 从 json 对象中获取 BigDecimal
     * 
     * @param jsonObj
     * @param key
     * @return
     * @return BigDecimal
     * @throws Exception
     *             exception
     * @author xu_cc
     * @Date 创建时间：2017年7月14日 下午6:02:05
     */
    private BigDecimal getBigDecimalFromJson(JSONObject jsonObj, String key) {
        return BigDecimal.valueOf(jsonObj.getDouble(key));
    }

    /**
     * 分页查询活动信息
     * 
     * @param pageParam
     *            分页参数
     * @param paramMap
     *            查询参数
     * @return PageBean 分页参数和分页数据
     * @author xu_cc
     * @date 2017-09-27 23:24:51
     */
    @Override
    public PageBean listPromotionPage(PageParam pageParam, Map<String, Object> paramMap) {
        return promotionDao.listPromotionPage(pageParam, paramMap);
    }

    /**
     * 根据ID查询活动信息信息
     * 
     * @param id
     *            活动信息id
     * @return promotionEntity 活动信息对象
     * @author xu_cc
     * @date 2017-09-27 23:24:51
     */
    @Cacheable(value="promotion",key="'PROMOTION_'+#id")
    public PromotionEntity getPromotionById(Long id) {
        return promotionDao.getById(id.longValue());
    }

    /**
     * 根据条件查询活动信息
     * 
     * @param param
     * @return 数据列表
     * @author xu_cc
     * @date 2017-09-27 23:24:51
     */
    @Override
    public List<PromotionEntity> listPromotion(Map<String, Object> param) {
        return promotionDao.listPromotion(param);
    }

    /**
     * 删除活动信息
     * 
     * @param
     * @return int 返回删除记录条数
     * @author xu_cc
     * @date 2017-09-27 23:24:51
     */
    @Caching(evict = { 
            @CacheEvict(value = "promotion", key = "'PROMOTION_' + #id"),
            @CacheEvict(value = "promotion", key = "'PROMOTION_RULE_' + #id")})
    public int deletePromotionById(long id) {
        return promotionDao.deleteById(id);
    }

    /**
     * 查询活动规则总体信息
     * 
     * @param promotionId
     * @return
     */
    @Cacheable(value="promotion",key="'PROMOTION_RULE_'+#promotionId")
    public PromotionRulesEntity listPromotionRule(Long promotionId) {
        PromotionRulesEntity pre = new PromotionRulesEntity();
        // 查询活动基本信息
        PromotionEntity promotionEntity = promotionDao.getById(promotionId);
        pre.setPromtEntity(promotionEntity);
        // 查询活动规则
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("promotionId", promotionId);
        if (PromotionConstants.PROMOTION_TYPE.REDUCE.getCode().equals(String.valueOf(promotionEntity.getPromotionType()))) {
            // 满减
            List<PromotionRuleReduceEntity> reduceList = ruleReduceDao.listBy(param);
            pre.setReduceList(reduceList);
        } else if (PromotionConstants.PROMOTION_TYPE.GIFT.getCode().equals(String.valueOf(promotionEntity.getPromotionType()))) {
            // 满赠
            List<PromotionRuleGiftEntity> giftList = ruleGiftDao.listBy(param);
            pre.setGiftList(giftList);
        } else {
            // 满折
            List<PromotionRuleDiscountEntity> discountList = ruleDiscountDao.listBy(param);
            pre.setDiscountList(discountList);
        }
        return pre;
    }

    /**
     * 增加活动商品时段校验（同一时间段内同一商品不可参加多个活动）<br>
     * productCode<br>
     * beginTime<br>
     * endTime
     * 
     * @param paramMap
     * @return List<PromotionEntity>
     * @author xu_cc
     * @throws Exception
     *             exception
     * @Date 创建时间：2017年11月2日 下午4:38:19
     */
    public List<PromotionEntity> getPromotionProductByTime(List<Map<String, Object>> paramMap) {
        return promotionDao.getPromotionProductByTime(paramMap);
    }
}
